/*
 *  Copyright 2010 Wesley Gooch, Ryan Nix, Cody Wenzel.
 *  Montana State University - Spring Semester 2010
 *  Computer Science 450 - Compilers
 *  Project: Micro-Pascal Compiler
 */
package msu.compiler.scanner.fsas;

import msu.compiler.scanner.Tokenizer;
import msu.compiler.scanner.Token;

/**
 *
 * @author Cody Wenzel
 */
public class IdentifierFSA extends FSA {

    public IdentifierFSA(Tokenizer tokenizer) {
        super(tokenizer);
        initializeStates(5);
    }

    /**
     * Executes the IndentifierFSA state machine.
     *
     * (letter | "_"(letter | digit)){["_"](letter | digit)}
     *
     * @pre     The tokenizer is pointing at the first character of the
     *          current token which must be a letter or _
     *
     * @post    The tokenizer is pointing at the first character after
     *          the current token.
     *          A token has been generated.
     *          The token's lexeme contains an identifier
     */
    public void execute() {
        Character currentChar;
        while (notFinished()) {
            currentChar = getCurrentChar();
            switch (getCurrentState()) {
                case 0:
                    if (Tokenizer.isLetter(currentChar)) {
                        setAcceptState("s2", Token.MP_IDENTIFIER);
                        peekAhead();
                    } else if (currentChar == '_') {
                        setCurrentState("s1");
                        peekAhead();
                    } else {
                        fail();
                    }
                    break;
                case 1:
                    if (Tokenizer.isLetterOrDigit(currentChar)) {
                        setAcceptState("s2", Token.MP_IDENTIFIER);
                        peekAhead();
                    } else {
                        fail();
                    }
                    break;
                case 2:
                    if (Tokenizer.isLetterOrDigit(currentChar)) {
                        setAcceptState("s2", Token.MP_IDENTIFIER);
                        peekAhead();
                    } else if (currentChar == '_') {
                        setCurrentState("s3");
                        peekAhead();
                    } else {
                        fail();
                    }
                    break;
                case 3:
                    if (Tokenizer.isLetterOrDigit(currentChar)) {
                        setAcceptState("s2", Token.MP_IDENTIFIER);
                        peekAhead();
                    } else {
                        fail();
                    }
                    break;
                default:
                    fail();
                    break;
            }
        }
    }
}
